#include <ZombieManager.h>

// Constructores y destructores ----------------------------------------

template<> ZombieManager* Ogre::Singleton<ZombieManager>::ms_Singleton = 0;

ZombieManager::ZombieManager(btDiscreteDynamicsWorld* pWorld,
                             Ogre::SceneManager* pSceneManager,
                             Human* pHuman) :
  _pWorld(pWorld), _pSceneManager(pSceneManager), _pHuman(pHuman) {

  Ogre::Entity* pZombieEntity =
    _pSceneManager->createEntity("ZombieExampleEntity", ZOMBIEMESH);

  BtOgre::StaticMeshToShapeConverter converter(pZombieEntity);

  _pZombieCollisionShape = converter.createCylinder();

  _pSceneManager->destroyEntity("ZombieExampleEntity");
}

ZombieManager::~ZombieManager() {

  _swarms.clear();
  _zombies.clear();
  delete _pZombieCollisionShape;
}

// Ogre::Singleton -----------------------------------------------------

ZombieManager&
ZombieManager::getSingleton() {

  assert(ms_Singleton);
  return *ms_Singleton;
}

ZombieManager*
ZombieManager::getSingletonPtr() { return ms_Singleton; }

// Factory -------------------------------------------------------------

ZombieSwarm*
ZombieManager::createSwarm(OpenSteer::Vec3 position, int nZombies) {

  ZombieSwarm* pSwarm = new ZombieSwarm(_pWorld, _pZombieCollisionShape,
                                        _pSceneManager, position, _pHuman,
                                        nZombies);
  _swarms.push_back(pSwarm);

  return pSwarm;
}

Zombie*
ZombieManager::createZombie(OpenSteer::Vec3 position) {

  Zombie* pZombie = new Zombie(_pWorld, _pZombieCollisionShape,
                               _pSceneManager, position, _pHuman);
  _zombies.push_back(pZombie);

  return pZombie;
}

ZombieSpawner*
ZombieManager::createSpawner(OpenSteer::Vec3 position,
                             int spawnTime,  int maxZombies) {

  ZombieSpawner* pSpawner = new ZombieSpawner(position, this,
                                              _pHuman, spawnTime,
                                              maxZombies);
  _spawners.push_back(pSpawner);

  return pSpawner;
}

// Update --------------------------------------------------------------

void
ZombieManager::update(const float currentTime,
                      const float elapsedTime) {

  updateSwarms(currentTime, elapsedTime);
  updateZombies(currentTime, elapsedTime);
  updateSpawners(currentTime, elapsedTime);
}

void
ZombieManager::updateSwarms(const float currentTime,
                            const float elapsedTime) {

  for (_swarmsIt = _swarms.begin();
       _swarmsIt != _swarms.end();
       _swarmsIt++)
    (*_swarmsIt)->update(currentTime, elapsedTime);
}

void
ZombieManager::updateZombies(const float currentTime,
                             const float elapsedTime) {

  for (_zombiesIt = _zombies.begin();
       _zombiesIt != _zombies.end();
       _zombiesIt++)
    (*_zombiesIt)->update(currentTime, elapsedTime);
}

void
ZombieManager::updateSpawners(const float currentTime,
                              const float elapsedTime) {

  for (_spawnersIt = _spawners.begin();
       _spawnersIt != _spawners.end();
       _spawnersIt++)
    (*_spawnersIt)->update(currentTime, elapsedTime);
}
